<script setup lang="ts">
import { inject, onMounted, reactive, ref, watch } from 'vue';

import {
  ElCol,
  ElCollapse,
  ElCollapseItem,
  ElInput,
  ElInputNumber,
  ElOption,
  ElRadio,
  ElRadioGroup,
  ElRow,
  ElSelect,
  ElSlider,
} from 'element-plus';

import { lineCapList, lineJoinList, lineTypeList } from '#/assets/style';
import { usePublicStore } from '#/store';
import { getLineTypeUrl } from '#/utils';

const publicStore = usePublicStore();
const currentLayer = inject('currentSelectedLayer') as any;
const activeNames = ref(['renderParams']);
const lineType = ref();
const lineCap = ref();
const lineJoin = ref();
const singleColor = ref('#ff0000');
const opacity = ref(100);
const size = ref(currentLayer.value.type === 'line' ? 5 : 10);
const blur = ref(0);
const isCircleOpenOutline = ref('closed');
const singleValueRenderParams = reactive({
  layer: currentLayer.value.id,
  type: currentLayer.value.type,
  point: {
    outline: isCircleOpenOutline,
    layout: {
      visibility: 'visible',
    },
    paint: {
      'circle-blur': blur,
      'circle-color': singleColor,
      'circle-radius': size,
      'circle-opacity': opacity,
      'circle-stroke-color': '#ffff00',
      'circle-stroke-width': 5,
      'circle-stroke-opacity': 100,
    },
  },
  line: {
    layout: {
      'line-cap': 'butt',
      'line-join': 'miter',
      visibility: 'visible',
    },
    paint: {
      'line-blur': blur,
      'line-color': singleColor,
      'line-opacity': opacity,
      'line-width': size,
      // 'line-dasharray': [20, 20],
      'line-dasharray': [3, 3],
      // 'line-gap-width': 15
      'line-gap-width': 5,
    },
  },
  polygon: {
    layout: {
      visibility: 'visible',
    },
    paint: {
      'fill-color': singleColor,
      'fill-opacity': opacity,
      // 'fill-outline-color': '#000000'
      'fill-outline-color': '#ffffff',
    },
  },
} as any);
// watch(singleValueRenderParams, (newValue, oldValue) => {
//   console.log(`参数变化了，新值：${newValue}，旧值：${oldValue}`);
// }, { deep: true });
const circleBlur = ref(
  `blur(${singleValueRenderParams.point.paint['circle-blur']}px)`,
);

const currentLineType = ref('solid');

const getLineType = () => {
  if (
    singleValueRenderParams.line.paint['line-dasharray'].length === 0 &&
    !singleValueRenderParams.line.paint['line-gap-width']
  ) {
    currentLineType.value = 'solid';
  } else if (
    singleValueRenderParams.line.paint['line-dasharray'].length > 0 &&
    !singleValueRenderParams.line.paint['line-gap-width']
  ) {
    currentLineType.value = 'dashed';
  } else if (
    singleValueRenderParams.line.paint['line-dasharray'].length === 0 &&
    singleValueRenderParams.line.paint['line-gap-width']
  ) {
    currentLineType.value = 'double_solid';
  } else if (
    singleValueRenderParams.line.paint['line-dasharray'].length > 0 &&
    singleValueRenderParams.line.paint['line-gap-width']
  ) {
    currentLineType.value = 'double_dashed';
  }
};

const renderParamsReturn = () => {
  const renderParams =
    currentLayer.value.templateParams ?? currentLayer.value.renderParams;

  delete currentLayer.value.templateParams;
  if (currentLayer.value.type === 'circle') {
    if (renderParams.outline === 'open') {
      singleValueRenderParams.point.paint['circle-stroke-color'] =
        renderParams.paint['circle-stroke-color'];
      singleValueRenderParams.point.paint['circle-stroke-width'] =
        renderParams.paint['circle-stroke-width'];
      singleValueRenderParams.point.paint['circle-stroke-opacity'] =
        renderParams.paint['circle-stroke-opacity'];
    }
    isCircleOpenOutline.value = renderParams.outline;
    blur.value = renderParams.paint['circle-blur'];
    size.value = renderParams.paint['circle-radius'];
    singleColor.value = renderParams.paint['circle-color'];
    opacity.value = renderParams.paint['circle-opacity'];
  } else if (currentLayer.value.type === 'line') {
    singleValueRenderParams.line.layout['line-cap'] =
      renderParams.layout['line-cap'];
    singleValueRenderParams.line.layout['line-join'] =
      renderParams.layout['line-join'];
    blur.value = renderParams.paint['line-blur'];
    singleColor.value = renderParams.paint['line-color'];
    size.value = renderParams.paint['line-width'];
    opacity.value = renderParams.paint['line-opacity'];
    singleValueRenderParams.line.paint['line-dasharray'] =
      renderParams.paint['line-dasharray'];
    singleValueRenderParams.line.paint['line-gap-width'] =
      renderParams.paint['line-gap-width'];
  } else {
    singleColor.value = renderParams.paint['fill-color'];
    opacity.value = renderParams.paint['fill-opacity'];
    singleValueRenderParams.polygon.paint['fill-outline-color'] =
      renderParams.paint['fill-outline-color'];
  }
};

const drawCircle = () => {
  // console.log(singleValueRenderParams)
  const canvas = document.querySelector('#graph-preview') as any;
  const ctx = canvas.getContext('2d') as any;
  ctx.clearRect(0, 0, canvas.width, canvas.height);
  const radius = size.value;
  const color = singleColor.value;
  const circleOpacity = opacity.value;
  // console.log(radius, color)

  // const { outline, outlineColor, outlineOpacity, outlineWidth } = singleValueRenderParams.value.style.point
  const {
    'circle-stroke-color': outlineColor,
    'circle-stroke-opacity': outlineOpacity,
    'circle-stroke-width': outlineWidth,
  } = singleValueRenderParams.point.paint;
  const centerX = canvas.width / 2;
  const centerY = canvas.height / 2;
  // 判断轮廓线是否开启
  if (isCircleOpenOutline.value === 'open') {
    ctx.globalAlpha = outlineOpacity / 100;
    ctx.beginPath();
    // console.log(radius + outlineWidth / 2)
    ctx.arc(centerX, centerY, radius + outlineWidth / 2, 0, 2 * Math.PI);
    ctx.lineWidth = outlineWidth; // 轮廓线宽度
    ctx.strokeStyle = outlineColor; // 轮廓线颜色
    ctx.stroke();
    ctx.closePath();
  }
  ctx.globalAlpha = circleOpacity / 100;
  ctx.beginPath();
  ctx.arc(centerX, centerY, radius, 0, 2 * Math.PI);
  ctx.fillStyle = color;
  ctx.fill();
  ctx.closePath();
};
const drawLine = () => {
  // console.log(singleValueRenderParams)
  const canvas = document.querySelector('#graph-preview') as any;
  const ctx = canvas.getContext('2d') as any;
  const width = size.value;
  const color = singleColor.value;
  const lineOpacity = opacity.value;
  ctx.clearRect(0, 0, canvas.width, canvas.height);
  // console.log(ctx)
  ctx.setLineDash([]);
  ctx.lineCap = singleValueRenderParams.line.layout['line-cap'];
  ctx.lineJoin = singleValueRenderParams.line.layout['line-join'];

  ctx.strokeStyle = color;
  ctx.lineWidth = width;
  ctx.globalAlpha = lineOpacity / 100;
  if (
    currentLineType.value === 'dashed' ||
    currentLineType.value === 'double_dashed'
  ) {
    ctx.setLineDash([
      singleValueRenderParams.line.paint['line-dasharray'][0] * size.value,
      singleValueRenderParams.line.paint['line-dasharray'][1] * size.value,
    ]);
    // ctx.setLineDash([20, 20]);
    // console.log('设置了lineDash')
  }
  // console.log(ctx.lineDash)
  ctx.beginPath();
  ctx.moveTo(50, 50);
  ctx.lineTo(350, 50);
  ctx.stroke();
  if (
    currentLineType.value === 'double_solid' ||
    currentLineType.value === 'double_dashed'
  ) {
    if (currentLineType.value === 'double_dashed') {
      ctx.setLineDash([
        singleValueRenderParams.line.paint['line-dasharray'][0] * size.value,
        singleValueRenderParams.line.paint['line-dasharray'][1] * size.value,
      ]);
      // ctx.setLineDash([20, 20]);
    }
    ctx.globalAlpha = lineOpacity / 100;
    ctx.beginPath();
    ctx.moveTo(
      50,
      50 + singleValueRenderParams.line.paint['line-gap-width'] * size.value,
    );
    // ctx.moveTo(50, 50 + 15);
    ctx.lineTo(
      350,
      50 + singleValueRenderParams.line.paint['line-gap-width'] * size.value,
    );
    // ctx.lineTo(350, 50 + 15);
    ctx.stroke();
  }
};
const drawPolygon = () => {
  const canvas = document.querySelector('#graph-preview') as any;
  const context = canvas.getContext('2d') as any;
  context.clearRect(0, 0, canvas.width, canvas.height);

  const size = Math.min(canvas.width, canvas.height) * 0.8;
  const x = (canvas.width - size) / 2;
  const y = (canvas.height - size) / 2;
  context.globalAlpha = opacity.value / 100;
  context.fillStyle = singleColor.value;
  context.strokeStyle =
    singleValueRenderParams.polygon.paint['fill-outline-color'];
  context.lineWidth = 2;

  context.fillRect(x, y, size, size);
  context.strokeRect(x, y, size, size);
};
const drawEntry = () => {
  if (currentLayer.value.type === 'circle') {
    drawCircle();
  } else if (currentLayer.value.type === 'line') {
    drawLine();
  } else {
    drawPolygon();
  }
};
const changeBlur = () => {
  circleBlur.value = `blur(${singleValueRenderParams.point.paint['circle-blur']}px)`;
};

const changeLineType = (val: any) => {
  switch (val) {
    case 'dashed': {
      if (singleValueRenderParams.line.paint['line-dasharray'].length === 0) {
        singleValueRenderParams.line.paint['line-dasharray'] = [3, 3];
      }
      singleValueRenderParams.line.paint['line-gap-width'] = 0;
      break;
    }
    case 'double_dashed': {
      if (singleValueRenderParams.line.paint['line-dasharray'].length === 0) {
        singleValueRenderParams.line.paint['line-dasharray'] = [3, 3];
      }
      if (!singleValueRenderParams.line.paint['line-gap-width']) {
        singleValueRenderParams.line.paint['line-gap-width'] = 5;
      }
      break;
    }
    case 'double_solid': {
      singleValueRenderParams.line.paint['line-dasharray'] = [];
      if (!singleValueRenderParams.line.paint['line-gap-width']) {
        singleValueRenderParams.line.paint['line-gap-width'] = 5;
      }
      break;
    }
    case 'solid': {
      singleValueRenderParams.line.paint['line-dasharray'] = [];
      singleValueRenderParams.line.paint['line-gap-width'] = 0;
      break;
    }
  }
  let img = null;
  lineTypeList.forEach((item: any) => {
    if (item.value === val) {
      img = getLineTypeUrl(item.value);
    }
  });
  // console.log(img)
  lineType.value.$el.children[0].children[0].children[1].setAttribute(
    'style',
    `
        background: url(${img}) no-repeat; 
				background-position: 10px center; 
				background-size: 300px 20px; 
				text-indent: 320px;
				`,
  );
  drawLine();
};
const changeLineCap = (val: any) => {
  let img = null;
  lineCapList.forEach((item: any) => {
    if (item.value === val) {
      img = getLineTypeUrl(item.imgName);
    }
  });
  // console.log(img)
  lineCap.value.$el.children[0].children[0].children[1].setAttribute(
    'style',
    `
        background: url(${img}) no-repeat; 
				background-position: 10px center; 
				background-size: 30px 20px; 
				text-indent: 50px;
				`,
  );
  drawLine();
};
const changeLineJoin = (val: any) => {
  let img = null;
  lineJoinList.forEach((item: any) => {
    if (item.value === val) {
      img = getLineTypeUrl(item.imgName);
    }
  });
  // console.log(img)
  lineJoin.value.$el.children[0].children[0].children[1].setAttribute(
    'style',
    `
        background: url(${img}) no-repeat; 
				background-position: 10px center; 
				background-size: 30px 20px; 
				text-indent: 50px;
				`,
  );
  drawLine();
};

watch(
  singleValueRenderParams,
  () => {
    publicStore.setRenderOptions(singleValueRenderParams);
  },
  {
    deep: true,
  },
);
onMounted(() => {
  const { renderType, templateParams } = currentLayer.value;
  //  当原先渲染方式是该方式时，或现在渲染方式是来自于模板时，需要参数恢复（赋值）
  if (renderType[1] === 'singleValueRender' || templateParams) {
    renderParamsReturn();
    getLineType();
  }
  changeBlur();
  // publicStore.setRenderOptions(singleValueRenderParams)
  if (currentLayer.value.type === 'circle') {
    drawCircle();
  } else if (currentLayer.value.type === 'line') {
    // changeLineType('solid')
    changeLineType(currentLineType.value);
    // changeLineCap('butt')
    changeLineCap(singleValueRenderParams.line.layout['line-cap']);
    // changeLineJoin('miter')
    changeLineJoin(singleValueRenderParams.line.layout['line-join']);
    drawLine();
  } else {
    drawPolygon();
  }
});
</script>

<template>
  <div class="all">
    <ElRow class="itemRow">
      <ElCol :span="4">
        <span class="label-style"> 预览： </span>
      </ElCol>
      <ElCol :span="20">
        <div id="canvas-container">
          <canvas id="graph-preview" width="380" height="100"></canvas>
        </div>
      </ElCol>
    </ElRow>
    <ElRow class="itemRow">
      <ElCol :span="24">
        <ElCollapse v-model="activeNames" accordion>
          <ElCollapseItem title="渲染参数" name="renderParams">
            <ElRow class="itemRow">
              <ElCol :span="4">
                <span class="label-style"> 颜色： </span>
              </ElCol>
              <ElCol :span="20">
                <ElInput
                  @input="drawEntry"
                  class="colorInput"
                  v-model="singleColor"
                  type="color"
                  size="small"
                />
              </ElCol>
            </ElRow>
            <ElRow class="itemRow">
              <ElCol :span="6">
                <span class="label-style"> 不透明度： </span>
              </ElCol>
              <ElCol :span="18">
                <ElSlider
                  @input="drawEntry"
                  v-model.number="opacity"
                  show-input
                  size="small"
                />
              </ElCol>
            </ElRow>
            <ElRow v-if="currentLayer.type !== 'fill'" class="itemRow">
              <ElCol :span="4">
                <span class="label-style">
                  {{ currentLayer.type === 'circle' ? '大小：' : '宽度：' }}
                </span>
              </ElCol>
              <ElCol :span="20">
                <ElInput
                  @input="drawEntry"
                  v-model.number="size"
                  placeholder="Please input"
                  size="small"
                >
                  <template #append>像素</template>
                </ElInput>
              </ElCol>
            </ElRow>
          </ElCollapseItem>
          <ElCollapseItem title="其他样式" name="otherStyle">
            <template v-if="currentLayer.type === 'circle'">
              <ElRow class="itemRow">
                <ElCol :span="4">
                  <span class="label-style"> 模糊度： </span>
                </ElCol>
                <ElCol :span="20">
                  <ElSlider
                    @input="changeBlur"
                    v-model.number="blur"
                    show-input
                    :max="30"
                    size="small"
                  />
                </ElCol>
              </ElRow>
              <ElRow class="itemRow">
                <ElCol :span="8">
                  <span class="label-style"> 是否开启外轮廓线： </span>
                </ElCol>
                <ElCol :span="16">
                  <div>
                    <ElRadioGroup
                      v-model="isCircleOpenOutline"
                      @change="drawEntry"
                    >
                      <ElRadio label="open" size="small">开启</ElRadio>
                      <ElRadio label="closed" size="small">关闭</ElRadio>
                    </ElRadioGroup>
                  </div>
                </ElCol>
              </ElRow>
              <ElRow class="itemRow">
                <ElCol :span="6">
                  <span class="label-style"> 外轮廓线颜色： </span>
                </ElCol>
                <ElCol :span="18">
                  <ElInput
                    @input="drawEntry"
                    class="colorInput"
                    v-model="
                      singleValueRenderParams.point.paint['circle-stroke-color']
                    "
                    type="color"
                    :disabled="isCircleOpenOutline === 'closed'"
                    size="small"
                  />
                </ElCol>
              </ElRow>
              <ElRow class="itemRow">
                <ElCol :span="6">
                  <span class="label-style"> 外轮廓线线宽： </span>
                </ElCol>
                <ElCol :span="18">
                  <ElInput
                    @input="drawEntry"
                    v-model.number="
                      singleValueRenderParams.point.paint['circle-stroke-width']
                    "
                    placeholder="Please input"
                    :disabled="isCircleOpenOutline === 'closed'"
                    size="small"
                  >
                    <template #append>像素</template>
                  </ElInput>
                </ElCol>
              </ElRow>
              <ElRow class="itemRow">
                <ElCol :span="8">
                  <span class="label-style"> 外轮廓线不透明度： </span>
                </ElCol>
                <ElCol :span="16">
                  <ElSlider
                    @input="drawEntry"
                    v-model.number="
                      singleValueRenderParams.point.paint[
                        'circle-stroke-opacity'
                      ]
                    "
                    :disabled="isCircleOpenOutline === 'closed'"
                    show-input
                    size="small"
                  />
                </ElCol>
              </ElRow>
            </template>
            <template v-else-if="currentLayer.type === 'line'">
              <ElRow class="itemRow">
                <ElCol :span="4">
                  <span class="label-style"> 模糊度： </span>
                </ElCol>
                <ElCol :span="20">
                  <ElSlider
                    size="small"
                    @input="changeBlur"
                    v-model.number="blur"
                    show-input
                    :max="30"
                  />
                </ElCol>
              </ElRow>
              <ElRow class="itemRow">
                <ElCol :span="4">
                  <span class="label-style"> 描边样式： </span>
                </ElCol>
                <ElCol :span="20">
                  <ElSelect
                    ref="lineType"
                    style="width: 100%"
                    size="small"
                    v-model="currentLineType"
                    placeholder="请选择线型"
                    @change="changeLineType"
                  >
                    <ElOption
                      v-for="item in lineTypeList"
                      :key="item.id"
                      :label="item.label"
                      :value="item.value"
                    >
                      <ElRow type="flex" :gutter="20" justify="center">
                        <ElCol :span="18">
                          <img
                            :src="getLineTypeUrl(item.value)"
                            style="float: left; height: 30px"
                          />
                        </ElCol>
                        <ElCol :span="6">
                          <span>{{ item.label }}</span>
                        </ElCol>
                      </ElRow>
                    </ElOption>
                  </ElSelect>
                </ElCol>
              </ElRow>
              <ElRow
                class="itemRow"
                v-if="['double_dashed', 'dashed'].includes(currentLineType)"
              >
                <ElCol :span="4" style="display: flex; align-items: center">
                  <span class="label-style"> 虚线长度： </span>
                </ElCol>
                <ElCol :span="3">
                  <span class="label-style"> 实部： </span>
                </ElCol>
                <ElCol :span="6" class="define-input-number">
                  <ElInputNumber
                    v-model="
                      singleValueRenderParams.line.paint['line-dasharray'][0]
                    "
                    :min="1"
                    :step="1"
                    controls-position="right"
                    @change="drawEntry"
                    size="small"
                  />
                  <div class="define-append">线宽</div>
                </ElCol>
                <ElCol :span="3" :offset="2">
                  <span class="label-style"> 虚部： </span>
                </ElCol>
                <ElCol :span="6" class="define-input-number">
                  <ElInputNumber
                    v-model="
                      singleValueRenderParams.line.paint['line-dasharray'][1]
                    "
                    :min="1"
                    :step="1"
                    controls-position="right"
                    @change="drawEntry"
                    size="small"
                  />
                  <div class="define-append">线宽</div>
                </ElCol>
              </ElRow>
              <ElRow
                v-if="
                  ['double_solid', 'double_dashed'].includes(currentLineType)
                "
                class="itemRow"
              >
                <ElCol :span="4">
                  <span class="label-style"> 线隙宽度： </span>
                </ElCol>
                <ElCol :span="20">
                  <ElInput
                    @input="drawEntry"
                    v-model.number="
                      singleValueRenderParams.line.paint['line-gap-width']
                    "
                    placeholder="Please input"
                    size="small"
                  >
                    <template #append>像素</template>
                  </ElInput>
                </ElCol>
              </ElRow>
              <ElRow class="itemRow">
                <ElCol :span="4">
                  <span class="label-style"> 端点样式： </span>
                </ElCol>
                <ElCol :span="20">
                  <ElSelect
                    ref="lineCap"
                    style="width: 100%"
                    size="small"
                    v-model="singleValueRenderParams.line.layout['line-cap']"
                    placeholder="请选择端点样式"
                    @change="changeLineCap"
                  >
                    <ElOption
                      v-for="item in lineCapList"
                      :key="item.id"
                      :label="item.label"
                      :value="item.value"
                    >
                      <ElRow type="flex" :gutter="20" justify="center">
                        <ElCol :span="4">
                          <img
                            :src="getLineTypeUrl(item.imgName)"
                            style="float: left; height: 30px"
                          />
                        </ElCol>
                        <ElCol :span="20">
                          <span>{{ item.label }}</span>
                        </ElCol>
                      </ElRow>
                    </ElOption>
                  </ElSelect>
                </ElCol>
              </ElRow>
              <ElRow class="itemRow">
                <ElCol :span="4">
                  <span class="label-style"> 连接样式： </span>
                </ElCol>
                <ElCol :span="20">
                  <ElSelect
                    ref="lineJoin"
                    style="width: 100%"
                    size="small"
                    v-model="singleValueRenderParams.line.layout['line-join']"
                    placeholder="请选择端点样式"
                    @change="changeLineJoin"
                  >
                    <ElOption
                      v-for="item in lineJoinList"
                      :key="item.id"
                      :label="item.label"
                      :value="item.value"
                    >
                      <ElRow type="flex" :gutter="20" justify="center">
                        <ElCol :span="4">
                          <img
                            :src="getLineTypeUrl(item.imgName)"
                            style="float: left; height: 30px"
                          />
                        </ElCol>
                        <ElCol :span="20">
                          <span>{{ item.label }}</span>
                        </ElCol>
                      </ElRow>
                    </ElOption>
                  </ElSelect>
                </ElCol>
              </ElRow>
            </template>
            <template v-else>
              <ElRow class="itemRow">
                <ElCol :span="6">
                  <span class="label-style"> 外轮廓线颜色： </span>
                </ElCol>
                <ElCol :span="18">
                  <ElInput
                    @input="drawEntry"
                    class="colorInput"
                    v-model="
                      singleValueRenderParams.polygon.paint[
                        'fill-outline-color'
                      ]
                    "
                    type="color"
                    size="small"
                  />
                </ElCol>
              </ElRow>
            </template>
          </ElCollapseItem>
        </ElCollapse>
      </ElCol>
    </ElRow>
  </div>
</template>

<style lang="scss" scoped>
.all {
  width: 100%;
}

.itemRow {
  width: 100%;
  padding: 5px;
}

.el-input {
  width: 100%;
}

.label-style {
  font-size: 15px;
}

.colorInput {
  caret-color: transparent;
}

:deep(.colorInput .el-input__inner:hover) {
  cursor: pointer;
}

canvas {
  /* border: 1px solid rgb(171, 171, 171); */
}

#graph-preview {
  position: absolute;
  top: 0;
  left: 0;
}

:deep(.el-collapse-item__header) {
  font-size: 15px;
  font-weight: 600;
}

#canvas-container {
  position: relative;
  width: 380px;
  height: 100px;
  /* stylelint-disable-next-line value-keyword-case */
  filter: v-bind(circleBlur);

  /* 设置模糊效果 */
}

/* 自定义数字输入框append  */
.define-input-number {
  display: flex;
  width: 100%;
  border: 1px solid #dcdfe6;
  border-radius: 8px;

  .el-input-number--mini {
    flex: 1;
  }

  :deep(.el-input__inner) {
    border: none !important;
  }
}

.define-append {
  display: inline-block;
  width: 40px;
  height: 26px;
  padding: 0 3px;
  font-size: 12px;
  line-height: 26px;
  color: #909399;
  text-align: center;
  background: #f5f7fa;
  border-left: none;
}
</style>
